package net.jforum.entities;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.jforum.view.forum.common.PostCommon;

/**
 * An helper class that holds changes made to the pool.
 * 
 * @author Rafael Steil
 * @version $Id$
 */
public class PollChanges {
	private List deletedOptions = new ArrayList();
	private List newOptions = new ArrayList();
	private List changedOptions = new ArrayList();

	private boolean hasChanges;

	private Poll first;
	private Poll second;

	/**
	 * @param first
	 *            The "complete", most recent poll version. Usually the one
	 *            that's in the database.
	 * @param second
	 *            The poll to compare with. It usually will be a poll filled by
	 *            {@link PostCommon#fillPostFromRequest()}, so matches will be
	 *            done againts the existing poll and the data comming from the
	 *            server.
	 */
	public PollChanges(Poll first, Poll second) {
		this.first = first;
		this.second = second;
	}

	public void addChangedOption(PollOption option) {
		this.changedOptions.add(option);
		this.hasChanges = true;
	}

	public List getChangedOptions() {
		return this.changedOptions;
	}

	public void addDeletedOption(PollOption option) {
		this.deletedOptions.add(option);
		this.hasChanges = true;
	}

	public List getDeletedOptions() {
		return this.deletedOptions;
	}

	public void addNewOption(PollOption option) {
		this.newOptions.add(option);
		this.hasChanges = true;
	}

	public List getNewOptions() {
		return this.newOptions;
	}

	public boolean hasChanges() {
		this.searchForChanges();
		return this.hasChanges;
	}

	private void searchForChanges() {
		if (first == null || second == null) {
			return;
		}

		boolean isSame = first.getLabel().equals(second.getLabel());
		isSame &= first.getLength() == second.getLength();

		this.hasChanges = !isSame;

		List firstOptions = first.getOptions();
		List secondOptions = second.getOptions();

		int firstSize = firstOptions.size();
		int secondSize = secondOptions.size();
		int maxCount = Math.min(firstSize, secondSize);

		// Search for changes in existing options
		for (Iterator iter = firstOptions.iterator(); iter.hasNext();) {
			PollOption option = (PollOption) iter.next();
			PollOption changed = this.findOptionById(option.getId(),
					secondOptions);

			if (changed != null && !option.getText().equals(changed.getText())) {
				this.addChangedOption(changed);
			} else if (changed == null) {
				this.addDeletedOption(option);
			}
		}

		// Check if the incoming poll added options
		for (Iterator iter = secondOptions.iterator(); iter.hasNext();) {
			PollOption option = (PollOption) iter.next();

			if (this.findOptionById(option.getId(), firstOptions) == null) {
				this.addNewOption(option);
			}
		}
	}

	private PollOption findOptionById(int id, List options) {
		for (Iterator iter = options.iterator(); iter.hasNext();) {
			PollOption o = (PollOption) iter.next();

			if (o.getId() == id) {
				return o;
			}
		}

		return null;
	}
}